#include "QPropertyFormView.h"
#include "QPropertyModel.h"
#include "QPropertySet.h"
#include <QFormLayout>
#include <QGroupBox>
#include <QShowEvent>

#include "private/QPropertyFormView_p.h"

using namespace QPE;

QPropertyFormView::QPropertyFormView(QWidget* parent)
	: QPropertyFormWidget(new QPropertyFormViewPrivate(), parent)
{
	//
}

QPropertyFormView::QPropertyFormView(QPropertyModel* model, QWidget *parent)
	: QPropertyFormWidget(new QPropertyFormViewPrivate(), parent)
{
	setModel(model);
}

QPropertyFormView::QPropertyFormView(QPropertySet* property_set, QWidget *parent)
	: QPropertyFormWidget(new QPropertyFormViewPrivate(), parent)
{
	setPropertySet(property_set);
}

QPropertyFormView::~QPropertyFormView()
{
	// Nothing to do
}

void QPropertyFormView::build()
{
	QPropertyFormWidget::build();

	// Go through all sub widgets and connect
	connectPropertyFormWidget(this);
}

void QPropertyFormView::setModel(QPropertyModel *model)
{
	// Remove old model or set
	removeModelAndSet();

	// Set model
	static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model = model;
	if(model) {
		// Set the property list
		if(model->getPropertySet())
			d_ptr->Properties = model->getPropertySet()->getRootProperties();

		// Connect signals // todo: more signals neccesary!!!
		connect(model, SIGNAL(destroyed()), this, SLOT(modelDestroyed()));
		connect(model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(rowsInserted(QModelIndex,int,int)));
		connect(model, SIGNAL(modelReset()), this, SLOT(modelReset()));
		connect(model, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(rowsRemoved(QModelIndex,int,int)));
	}

	// Build the widget
	updatePropertyList();
}

void QPropertyFormView::setPropertySet(QPropertySet* property_set)
{
	// Remove old model or set
	removeModelAndSet();

	// Set property set
	static_cast<QPropertyFormViewPrivate*>(d_ptr)->PropertySet = property_set;
	if(property_set) {
		// Set the property list
		d_ptr->Properties = property_set->getRootProperties();
	}

	// Build the widget
	updatePropertyList();
}

void QPropertyFormView::rowsRemoved(const QModelIndex &parent, int start, int end)
{
	// todo: Only rebuild the neccessary parts
	Q_UNUSED(parent)
	Q_UNUSED(start)
	Q_UNUSED(end)
	updatePropertyList();
}

void QPropertyFormView::rowsInserted(const QModelIndex &parent, int start, int end)
{
	// todo: Only rebuild the neccessary parts
	Q_UNUSED(parent)
	Q_UNUSED(start)
	Q_UNUSED(end)
	updatePropertyList();
}

void QPropertyFormView::modelReset()
{
	updatePropertyList();
}

void QPropertyFormView::modelDestroyed()
{
	removeModelAndSet();
	updatePropertyList();
}

void QPropertyFormView::dataChanged(const QModelIndex &top_left, const QModelIndex &bottom_right)
{
	if(static_cast<QPropertyFormViewPrivate*>(d_ptr)->IgnoreDataChangedSignal)
		return;
	// todo: handle data changes
}

void QPropertyFormView::dataSubmitted(QProperty *property)
{
	QPropertyModel* tmpModel = static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model;

	if(tmpModel && d_ptr->UpdateEditors) {
		static_cast<QPropertyFormViewPrivate*>(d_ptr)->IgnoreDataChangedSignal = true;
		tmpModel->onDataChangedByModel(property);
		static_cast<QPropertyFormViewPrivate*>(d_ptr)->IgnoreDataChangedSignal = false;
	}
}

void QPropertyFormView::showEvent(QShowEvent *event)
{
	Q_UNUSED(event)
	if(static_cast<QPropertyFormViewPrivate*>(d_ptr)->NeedsRebuild)
		build();
	static_cast<QPropertyFormViewPrivate*>(d_ptr)->NeedsRebuild = false;
}

void QPropertyFormView::updatePropertyList()
{
	QPropertyModel* tmpModel = static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model;
	QPropertySet* tmpSet = static_cast<QPropertyFormViewPrivate*>(d_ptr)->PropertySet;

	if(tmpModel && tmpModel->getPropertySet())
		d_ptr->Properties = tmpModel->getPropertySet()->getRootProperties();
	else if(tmpSet)
		d_ptr->Properties = tmpSet->getRootProperties();
	else
		d_ptr->Properties.clear();

	if(isVisible())
		build();
	else
		static_cast<QPropertyFormViewPrivate*>(d_ptr)->NeedsRebuild = true;
}

void QPropertyFormView::removeModelAndSet()
{
	if(static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model) {
		disconnect(static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model, 0, this, 0);
		static_cast<QPropertyFormViewPrivate*>(d_ptr)->Model = NULL;
	}

	static_cast<QPropertyFormViewPrivate*>(d_ptr)->NeedsRebuild = true;
	d_ptr->Properties.clear();
	static_cast<QPropertyFormViewPrivate*>(d_ptr)->PropertySet = NULL;
}

void QPropertyFormView::connectPropertyFormWidget(QPropertyFormWidget *widget)
{
	if(!widget)
		return;

	connect(widget, SIGNAL(propertyDataSubmitted(QProperty*)), this, SLOT(dataSubmitted(QProperty*)));
	QList<QPropertyFormWidget*> tmpList = widget->getChildPropertyFormWidgets();

	foreach(QPropertyFormWidget* tmpEditorWidget, tmpList) {
		connectPropertyFormWidget(tmpEditorWidget);
	}
}
